#include <cstring>
#include "xcfgreader.hpp"

void xstart_element(void* udata, const char *tag, const char **attr){
	xml_config_reader* xm=(xml_config_reader*)udata;
	xm->tagfull.push_back(tag);
	
	string stag;
	for(int i=0;i<xm->tagfull.size();i++){
		stag.append(xm->tagfull[i]);
		if(i<xm->tagfull.size()-1) stag.append(".");
	}
	xm->PushPair(stag,"");
	stag.append(".");
	
	for(int n=0;attr[n];n+=2){
		xm->PushPair(stag+attr[n],attr[n+1]);
	}
}

void xend_element(void* udata, const char* tag) {
	xml_config_reader* xm=(xml_config_reader*)udata;
	xm->tagfull.erase(xm->tagfull.end());
}

xml_config_reader::xml_config_reader(const char* cfgfile) {
	if(cfgfile){
		strcpy(ConfigFile,cfgfile);
		Read(cfgfile);
	}
}

#define BUFSIZE 2048

void xml_config_reader::Read(const string cfg_fl){
	strcpy(ConfigFile,cfg_fl.c_str());
	
	char buf[BUFSIZE];

	XML_Parser parser=XML_ParserCreate(NULL);
	XML_SetUserData(parser, this);
	XML_SetElementHandler(parser, xstart_element, xend_element);

 	ifstream xmlinput(cfg_fl.c_str());
 	if(xmlinput.fail()) THROWSTR("can not open file",cfg_fl.c_str());
 	int len,done;

	int cnt=0;
	 
	do {
		xmlinput.read(buf,BUFSIZE);
		len=xmlinput.gcount();
		done=len<BUFSIZE;
		if (!XML_Parse(parser, buf, len, done)){
			ErrorHandler(parser);
		}
	}while(!done);

	XML_ParserFree(parser);
}

void xml_config_reader::ErrorHandler(void* errstuff){
	XML_Parser parser=(XML_Parser)errstuff;
	char serr[512];
	XML_Error errno=XML_GetErrorCode(parser);
	int lino=XML_GetCurrentLineNumber(parser);
	
	switch(errno){
/*		case XML_ERROR_INVALID_TOKEN:
			sprintf(serr,"Warning: %s (%d) at line %d",XML_ErrorString(errno),errno,lino);
			std::cerr << serr << "\n";
			break;
*/		default:
			sprintf(serr,"file=%s: %s (%d) at line %d",ConfigFile,XML_ErrorString(errno),errno,lino);
			THROW(serr);
	}
}
